跳到主要内容

自治事务

自治事务的创建

自治事务是由另一个事务(主事务)启动的独立事务,它在执行SQL操作并提交或回滚,而无需提交或回滚主事务。并且其还具有如下特点:

自治事务不与主事务共享事务资源(如锁)。

自治事务不依赖于主事务。例如,如果主事务回滚,则嵌套事务会回滚,但自治事务不会回滚。

自治事务提交的更改会立即对其他事务可见。

自治事务的异常部分属于外部事务,自治事务中引发的异常会导致事务级回滚,而非语句级回滚。

语法

descript

自治事务的使用

  • ORACLE模式下运行。

  • 声明部分将例程标记为自治事务。

  • 应用场景包括:存储过程、函数、包、触发器。

  • 不支持重复声明自治事务。

  • 不支持在嵌套块内声明自治事务。

  • 当进入自治例程的可执行部分时,主事务暂停。回退自治例程后,主事务将恢复。

  • COMMIT并结束活动的自治事务,但例程未执行结束。

  • 保存点的作用域是在其中定义它的事务。事实上,主事务和自治事务可以使用相同的保存点名称。

  • 自治例程依然属于当前会话,如时间格式、序列等以会话粒度使用的功能。自治例程与外部保持一致。

  • 会话级隔离级别设置,自治事务设置后影响外部主事务事务属性,与其共享。

  • 事务级隔离级别或属性设置,自治事务设置仅影响本事务,不影响外部主事务。亦或是自治例程内commit后由下一个语句开启的新事务,同样不受影响。

示例

create table employees(employee_id varchar(64),amount int,salary int);
insert into employees values(100,100,1000);
set environment sqlmode 'oracle';

创建plsql匿名块

DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
emp_id NUMBER(6) := 100;
amount NUMBER(6,2) := 200;
BEGIN
UPDATE employees SET salary = salary - amount
WHERE employee_id = emp_id;
COMMIT;
END;
/

创建存储过程

CREATE OR REPLACE PROCEDURE lower_salary
(emp_id NUMBER, amount NUMBER)
AUTHID DEFINER AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE employees
SET salary = salary - amount
WHERE employee_id = emp_id;
COMMIT;
END lower_salary;
/

创建包

CREATE OR REPLACE PACKAGE emp_actions AUTHID DEFINER AS
FUNCTION raise_salary (emp_id NUMBER, sal_raise NUMBER)
RETURN NUMBER;
END emp_actions;
/
CREATE OR REPLACE PACKAGE BODY emp_actions AS
FUNCTION raise_salary (emp_id NUMBER, sal_raise NUMBER)
RETURN NUMBER IS
PRAGMA AUTONOMOUS_TRANSACTION;
new_sal NUMBER(8,2);
BEGIN
UPDATE employees SET salary =
salary + sal_raise WHERE employee_id = emp_id;
COMMIT;
SELECT salary INTO new_sal FROM employees
WHERE employee_id = emp_id;
RETURN new_sal;
END raise_salary;
END emp_actions;
/

创建触发器

CREATE TABLE log(
log_id NUMBER(6),up_date DATE,new_sal NUMBER(8,2),old_sal NUMBER(8,2));
CREATE TABLE emp(empno varchar(32),sal int);
CREATE OR REPLACE TRIGGER log_sal
BEFORE UPDATE OF sal ON emp FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO log (
log_id,
up_date,
new_sal,
old_sal
)
VALUES (
:old.empno,
SYSDATE,
:new.sal,
:old.sal
);
--COMMIT;
END;
/